<template>
  <div class="tree-container">
    <template v-for="item in treeData" :key="item[fieldKey.key]">
      <div :class="{ 'tree-item': true, 'active-tree-item': key == item[fieldKey.key] }" :style="{ '--level': level }">
        <div class="tree-icon">
          <slot name="icon-unfold">
            <icon-caret-down v-if="item[fieldKey.children] && unfoldList.includes(item[fieldKey.key])" @click="unfold(item)" />
          </slot>
          <slot name="icon-collapse">
            <icon-caret-right v-if="item[fieldKey.children] && !unfoldList.includes(item[fieldKey.key])" @click="unfold(item)" />
          </slot>
        </div>
        <div class="tree-item-title" @click="select(item)">
          <slot :node="item" :level="level">{{ item[fieldKey.title] }}</slot>
        </div>
        <slot name="option-icon" :node="item" :level="level"></slot>
      </div>
      <RectificationType
        v-if="item[fieldKey.children] && unfoldList.includes(item[fieldKey.key])"
        :treeData="item[fieldKey.children]"
        :field="field"
        :level="level + 1"
        v-model:value="key"
      >
        <template #default="{ node, level }">
          <slot :node="node" :level="level"></slot>
        </template>
        <template #option-icon="{ node, level }">
          <slot name="option-icon" :node="node" :level="level"></slot>
        </template>
      </RectificationType>
    </template>
  </div>
</template>

<script setup lang="ts">
/**
 * TODO: 该tree组件继承system树组件，两个可以合并
 */
import { computed } from "vue";
import type { PropType } from "vue";
import RectificationType from "./index.vue";

const defaultField = {
  title: "title",
  children: "children",
  key: "key"
};

const props = defineProps({
  treeData: {
    type: Array as PropType<{ [key: string]: any }[]>,
    default: () => []
  },
  field: {
    type: Object as PropType<{ [key: string]: any }>
  },
  level: {
    type: Number,
    default: 1
  },
  value: {
    type: String,
    defeult: ""
  },
  defaultUnfold: {
    type: Array as PropType<string[]>,
    default: () => []
  }
});
const autoUnfold = (tree: any[]): any => {
  for (const node of tree) {
    if (node[fieldKey.value.key] === key.value) {
      return [];
    }
    if (node.children) {
      const childPath = autoUnfold(node.children);
      if (childPath) {
        unfoldList.value.push(node[fieldKey.value.key]);
        return [node, ...childPath];
      }
    }
  }
  return undefined;
};
watch(
  () => props.treeData,
  () => {
    autoUnfold(props.treeData);
  }
);
const fieldKey = computed(() => ({
  key: props.field?.key || defaultField.key,
  title: props.field?.title || defaultField.title,
  children: props.field?.children || defaultField.children
}));
const emit = defineEmits(["change", "update:value"]);

const key = computed({
  get: () => {
    return props.value;
  },
  set: val => {
    emit("update:value", val);
    emit("change", val);
  }
});
const unfoldList = ref<string[]>([...props.defaultUnfold]);
const unfold = (item: { [key: string]: any }) => {
  const isHave = unfoldList.value.includes(item[fieldKey.value.key]);
  unfoldList.value = isHave
    ? unfoldList.value.filter(v => v != item[fieldKey.value.key])
    : [...unfoldList.value, item[fieldKey.value.key]];
};
const select = (item: { [key: string]: any }) => {
  // if (!item[fieldKey.value.children]) key.value = item[fieldKey.value.key];
  // else unfold(item);
  key.value = item[fieldKey.value.key];
};
onMounted(() => {
  autoUnfold(props.treeData);
});
</script>

<style lang="scss" scoped>
.tree-item {
  padding-left: calc(var(--level) * 16px);
  height: 32px;
  display: flex;
  line-height: 32px;
  cursor: pointer;
  padding-right: 16px;

  .tree-icon {
    width: 20px;
  }

  .tree-item-title {
    display: flex;
    flex: 1;
    justify-content: space-between;
    align-items: center;
  }
}

.active-tree-item {
  background: #d9e8ff;
  color: #007dff;
}
</style>
